package com.fufu.fileexport;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 多线程实现
 */
public class ExcelExportMulThread {

    public static void main(String[] args) {
        long l = System.currentTimeMillis();
        System.out.println("当前系统时间："+new Date());
        // 场景问题一，优化大量数据导出时可能存在的oom问题
        ArrayList<DataType> data = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            DataType dataType = new DataType();
            dataType.setColumn1("数据"+i);
            dataType.setColumn2("数据"+i);
            dataType.setColumn3("数据"+i);
            dataType.setColumn4("数据"+i);
            dataType.setColumn5("数据"+i);
            dataType.setColumn6("数据"+i);
            dataType.setColumn7("数据"+i);
            dataType.setColumn8("数据"+i);
            dataType.setColumn9("数据"+i);
            dataType.setColumn10("数据"+i);
            dataType.setColumn11("数据"+i);
            dataType.setColumn12("数据"+i);
            data.add(dataType);
        }

        String directoryPath  = "E:\\project\\wadaxi\\backup\\review\\parent\\Scene\\src\\main\\java\\com\\fufu\\fileexport\\file";
        String fileName = "output-mul.xlsx";
        String outputPath = directoryPath + File.separator + fileName;
        File file = new File(directoryPath);
        if (!file.exists()) {
            System.out.println("文件不存在");
            file.mkdirs(); // 创建所有不存在的父目录
        }
        System.out.println(outputPath);
        exportDataToExcel(data,outputPath);
        System.out.println("完成时间："+new Date());
        System.out.println("程序处理时间为："+( System.currentTimeMillis()-l));
        Runtime runtime = Runtime.getRuntime();
        long memory = runtime.totalMemory() - runtime.freeMemory();
        System.out.println("Memory used:"+memory);
    }

    public static void exportDataToExcel(List<DataType> data, String outputPath) {
//        Workbook workbook = new XSSFWorkbook(); // 创建Excel工作簿
        Workbook workbook = new SXSSFWorkbook(250000); // 通过设置内存策略来优化导出
        Sheet sheet = workbook.createSheet("Data"); // 创建工作表

        // 创建表头行
        Row headerRow = sheet.createRow(0);
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 根据你的数据类型设置表头
        String[] headers = {"Column1", "Column2", "Column3"}; // 示例表头
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }

        int threadCount = 4; // 线程数量
        int batchSize = data.size() / threadCount; // 单批次数据量
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        Object lock = new Object();

        for (int i = 0; i < threadCount; i++) {
            int startIndex = i * batchSize + 1; // 跳过表头
            int endIndex = (i == threadCount - 1) ? data.size() : (i + 1) * batchSize + 1;
            List<DataType> batchData = data.subList(startIndex - 1, endIndex - 1);
            executorService.submit(new ExportTask(sheet, batchData, startIndex, lock));
        }

        executorService.shutdown();
        try {
            executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 写入到文件系统
        try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {
            workbook.write(outputStream);
            ((SXSSFWorkbook) workbook).dispose();
            workbook.close(); // 关闭工作簿以释放资源
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
